package com.ruoyi.traplight.controller;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.Threads;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;

import com.ruoyi.permission.Dao.SerDevicePermi;
import com.ruoyi.permission.domain.BaseBlockPermiDeviceInfo;
import com.ruoyi.permission.domain.BlockPermiDeviceInfo;
import com.ruoyi.permission.domain.DevicePermiInsectInfo;
import com.ruoyi.permission.mapper.*;
import com.ruoyi.permission.service.PermiService;
import com.ruoyi.traplight.domain.*;
import com.ruoyi.traplight.domain.aliyun.DeviceProperties;
import com.ruoyi.traplight.mapper.TrapLightDataMapper;
import com.ruoyi.traplight.mapper.TrapLightDeviceMapper;
import com.ruoyi.traplight.service.TrapLightDeviceService;
import com.ruoyi.traplight.service.ModelService;
import com.ruoyi.traplight.service.PhotoService;
import com.ruoyi.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

import static com.ruoyi.utils.Threads.detectionVoidRequest;


@Api("测报灯控制类")
@Slf4j
@RestController
@RequestMapping("/device")
public class TrapLightController extends BaseController {
    @Autowired
    private TrapLightDeviceService deviceService;

    @Autowired
    private TrapLightDeviceMapper trapLightDeviceMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private SerDevicePermiMapper permiMapper;

    @Autowired
    private SerBlockDeviceMapper blockDeviceMapper;

    @Autowired
    private SerBaseBlockMapper baseBlockMapper;

    @Autowired
    private SerUnitBaseMapper unitBaseMapper;

    @Autowired
    private SerDeviceInsectMapper deviceInsectMapper;

    @Autowired
    private SerUnitUserMapper unitUserMapper;

    @Autowired
    private PermiService permiService;

    /**
     * 存储文件的路径
     */
    @Value("${ruoyi.profile}")
    private String profile;

    @Autowired
    private PhotoService photoService;
    private static String staticProfile;

    @PostConstruct
    public void profileinit() {
        staticProfile = profile;
        System.out.println("profile初始化");
    }

    /**
     * 模型检测图像处理路径
     */
    @Value("${ruoyi.detectionUrl}")
    private String detectionUrl;

    @Autowired
    private TrapLightDataMapper dataMapper;

    private static TrapLightDataMapper staticDataMapper;

    @PostConstruct
    public void dataMapperinit() {
        staticDataMapper = dataMapper;
        System.out.println("dataMapper初始化");
    }

    @Autowired
    private TrapLightDeviceMapper deviceMapper;

    @Autowired
    private ModelService modelService;
    private static ModelService staticmodelService;

    @PostConstruct
    public void modelServiceinit() {
        staticmodelService = modelService;
        System.out.println("modelService初始化");
    }

    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    /**
     * 日志上传（平板使用）
     *
     * @param file
     * @return
     */
    @PostMapping("/logUpload")
    public AjaxResult logUpload(@RequestParam("log") MultipartFile file) {
        try {
            String filePath = FileUploadUtils.uploadFileWithoutExtract(RuoYiConfig.getUploadPath(), file);
            return AjaxResult.success(filePath);
        } catch (IOException e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
    }

    /**
     * 调用服务
     *
     * @param deviceName
     * @param identifier
     * @return
     */
    @GetMapping("/invoke")
    public AjaxResult invokeThingService(String deviceName, String identifier) {
        try {
            String s = deviceService.invokeThingService(deviceName, identifier, "{}");
            if (s != null) {
                return Objects.requireNonNull(AjaxResult.success().put("MessageId", s)).put("Success", "true");
            } else {
                return AjaxResult.error().put("Success", "false");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
    }

    /**
     * 设置设备属性（异步）
     *
     * @param properties
     * @return
     */
    @PostMapping("/setProp")
    public AjaxResult setDeviceProperty(@RequestBody DeviceProperties properties) {
        try {
//            log.info(properties);
//            DeviceProperties deviceProperties = JSON.parseObject(properties, DeviceProperties.class, JSONReader.Feature.FieldBased);
//            log.info(deviceProperties.toString());
//            String jsonString = JSON.toJSONString(deviceProperties);
//            log.info(jsonString);
            String jsonString = JSON.toJSONString(properties);
            log.info(jsonString);
            String s = deviceService.setDeviceProperty(properties.getDeviceName(), jsonString);
            if (s != null) {
                return Objects.requireNonNull(AjaxResult.success().put("Success", "true")).put("MessageId", s);
            }
            return AjaxResult.success().put("Success", "false");
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
    }

    /**
     * 获取设备运行状态
     *
     * @param deviceName
     * @return
     */
    @GetMapping("/status")
    public AjaxResult getDeviceStatus(String deviceName) {
        try {
            String status = deviceService.getDeviceStatus(deviceName);
            if (status != null) {
                return Objects.requireNonNull(AjaxResult.success().put("deviceName", deviceName)).put("status", status);
            } else {
                return AjaxResult.error();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
    }

    @GetMapping("/getAllTraplightStatus")
    public AjaxResult getAllTraplightDeviceStatus() {
        Map<String, String> deviceStatusMap = new HashMap<>();
        try {
            List<DeviceDao> deviceDaoList = deviceMapper.selectDeviceList();
            for (DeviceDao deviceDao : deviceDaoList) {
                String deviceName = deviceDao.getDeviceName();
                String status = deviceService.getDeviceStatus(deviceName);
                if (status != null) {
                    deviceStatusMap.put(deviceName, status);
                } else {
                    return AjaxResult.error();
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
        return AjaxResult.success().put("deviceStatusMap", deviceStatusMap);
    }

    /**
     * 删除设备
     *
     * @param deviceName
     * @return
     */
    @DeleteMapping("/delete")
    public AjaxResult deleteDevice(String deviceName) {
        try {
            if (deviceService.deleteDevice(deviceName)) {
                return AjaxResult.success();
            } else {
                return AjaxResult.error();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
    }

    /**
     * 获取设备列表
     *
     * @return
     */
    @ApiOperation("getDeviceList")
    @GetMapping("/list")
    public TableDataInfo getDeviceList() {
        Long userIdL = SecurityUtils.getLoginUser().getUser().getUserId();
        Integer userId = Integer.valueOf(userIdL.intValue());
        Integer unitId = 0;
        if (userId != 1 && userId != 20) {
            unitId = unitUserMapper.selectByPrimaryKey(userId).getUnitId();
        }
        //管理员用户
        if (unitId == 0) {
            List<SerDevicePermi> serDevicePermiList = new ArrayList<>();
            DeviceDao deviceDao = new DeviceDao();
            return deviceService.selectDeviceInfoByCondition(deviceDao, serDevicePermiList);
        } else {
            //获取单位下所有设备
            List<BaseBlockPermiDeviceInfo> baseBlockPermiDeviceInfoList = permiService.selectAllDeviceByUnitId(unitId);
            List<SerDevicePermi> traplightDevicePermiList = new ArrayList<>();
            for (BaseBlockPermiDeviceInfo baseBlockPermiDeviceInfo : baseBlockPermiDeviceInfoList) {
                if (baseBlockPermiDeviceInfo.getTypeId() == 1) {
                    SerDevicePermi serDevicePermi = new SerDevicePermi().setDeviceName(baseBlockPermiDeviceInfo.getDeviceName()).setDeviceNo(baseBlockPermiDeviceInfo.getDeviceId())
                            .setDeviceType(baseBlockPermiDeviceInfo.getDeviceType()).setDeviceSerial(baseBlockPermiDeviceInfo.getDeviceSerial()).setId(baseBlockPermiDeviceInfo.getId());
                    traplightDevicePermiList.add(serDevicePermi);
                }
            }
            DeviceDao deviceDao = new DeviceDao();
            return deviceService.selectDeviceInfoByCondition(deviceDao, traplightDevicePermiList);
        }
    }

    /**
     * 根据地区获取该地区所有的设备id
     *
     * @param area
     * @return
     */
    @ApiOperation("getDeviceIdList")
    @GetMapping("/getDeviceIdByArea")
    public AjaxResult getDeviceIdByArea(String area) {
        List<Integer> idList = deviceService.selectDeviceIdByarea(area);
        if (!idList.isEmpty()) {
            return AjaxResult.success(idList);
        } else {
            return AjaxResult.error("无此地区的设备");
        }
    }

    /**
     * 根据条件获取设备
     *
     * @param deviceDao
     * @return
     */
    @ApiOperation("selectDeviceInfoByCondition")
    @GetMapping("/selectDeviceInfoByCondition")
    public TableDataInfo selectDeviceByCondition(DeviceDao deviceDao) {
        Long userIdL = SecurityUtils.getLoginUser().getUser().getUserId();
        Integer userId = Integer.valueOf(userIdL.intValue());
        Integer unitId = 0;
        if (userId != 1 && userId != 20) {
            unitId = unitUserMapper.selectByPrimaryKey(userId).getUnitId();
        }
        //管理员用户
        if (unitId == 0) {
            List<SerDevicePermi> serDevicePermiList = new ArrayList<>();
            return deviceService.selectDeviceInfoByCondition(deviceDao, serDevicePermiList);
        } else {
            //获取单位下所有设备
            List<BaseBlockPermiDeviceInfo> baseBlockPermiDeviceInfoList = permiService.selectAllDeviceByUnitId(unitId);
            List<SerDevicePermi> traplightDevicePermiList = new ArrayList<>();
            for (BaseBlockPermiDeviceInfo baseBlockPermiDeviceInfo : baseBlockPermiDeviceInfoList) {
                if (baseBlockPermiDeviceInfo.getTypeId() == 1) {
                    SerDevicePermi serDevicePermi = new SerDevicePermi().setDeviceName(baseBlockPermiDeviceInfo.getDeviceName()).setDeviceNo(baseBlockPermiDeviceInfo.getDeviceId())
                            .setDeviceType(baseBlockPermiDeviceInfo.getDeviceType()).setDeviceSerial(baseBlockPermiDeviceInfo.getDeviceSerial()).setId(baseBlockPermiDeviceInfo.getId());
                    traplightDevicePermiList.add(serDevicePermi);
                }
            }
            return deviceService.selectDeviceInfoByCondition(deviceDao, traplightDevicePermiList);
        }

    }

    /**
     * 修改设备昵称
     *
     * @param deviceName
     * @param nickName
     * @return
     */
    @GetMapping("/nickname")
    public AjaxResult setDeviceNickName(String deviceName, String nickName) {
        try {
            DeviceDao deviceDao = deviceMapper.selectDeviceByName(deviceName);
            if (deviceDao != null) {
                deviceDao.setNickName(nickName);
                deviceMapper.updateDevice(deviceDao);
                if (permiMapper.selectByDeviceSerial(deviceName) != null) {
                    SerDevicePermi devicePermiInfo = permiMapper.selectByDeviceSerial(deviceName);
                    devicePermiInfo.setDeviceName(nickName);
                    permiMapper.updateByPrimaryKeySelective(devicePermiInfo);
                }
                return Objects.requireNonNull(AjaxResult.success().put("deviceName", deviceName)).put("nickName", nickName);
            } else {
                return AjaxResult.error();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error();
        }
    }

    /**
     * 查询设备状态和属性
     *
     * @param deviceName
     * @return
     */
    @ApiOperation("deviceProperties")
    @GetMapping("/prop")
    public AjaxResult getDeviceProperties(String deviceName) {
        DeviceProperties deviceProperties = deviceService.getDeviceProperties(deviceName);
        DeviceDao deviceDao = deviceMapper.selectDeviceByName(deviceName);
        String manualId = deviceDao.getManualId();
        //最终使用的经纬度
        double longitudeFinal;
        double latitudeFinal;
        if (deviceProperties.getGeoLocation().getLatitude() == 0 || deviceProperties.getGeoLocation().getLongitude() == 0) {
            SerDevicePermi devicePermiInfo = permiMapper.selectByDeviceSerial(deviceName);
            if(devicePermiInfo.getLongitude()!=null && devicePermiInfo.getLatitude()!=null) {
                double longitude = devicePermiInfo.getLongitude();
                double latitude = devicePermiInfo.getLatitude();
                longitudeFinal = longitude;
                latitudeFinal = latitude;
            }else {
                longitudeFinal = 120.353233;
                latitudeFinal = 30.315333;
            }
            JSONObject weatherData = null;
            try {
                weatherData = LocationUtil.getWeatherData(latitudeFinal, longitudeFinal);
            } catch (Exception e) {
                log.info(e.getMessage());
            }
            //          1:有雨 0:无雨
            String weather = weatherData.getString("weather");
            int isRaining = (weather.contains("雨") || weather.contains("雪")) ? 1 : 0;
            float temperature = weatherData.getFloat("temperature");

            deviceProperties.setRainStatus(isRaining);
            deviceProperties.setTemperature(temperature);
        } else {
            DeviceProperties.GeoLocation geoLocation = deviceProperties.getGeoLocation();
            double longitude = geoLocation.getLongitude();
            double latitude = geoLocation.getLatitude();
            longitudeFinal = longitude;
            latitudeFinal = latitude;
            JSONObject weatherData = null;
            try {
                weatherData = LocationUtil.getWeatherData(latitude, longitude);
            } catch (Exception e) {
                log.info(e.getMessage());
            }
//          1:有雨 0:无雨
            String weather = weatherData.getString("weather");
            int isRaining = (weather.contains("雨") || weather.contains("雪")) ? 1 : 0;
            float temperature = weatherData.getFloat("temperature");
            deviceProperties.setRainStatus(isRaining);
            deviceProperties.setTemperature(temperature);
        }

        DeviceProperties properties = deviceMapper.selectDeviceStatus(deviceName);
        if (properties != null) {
            deviceMapper.updateDeviceStatus(deviceProperties);
        } else {
            deviceMapper.insertDeviceStatus(deviceProperties);
        }
        Map<String, Object> returnDeviceProperties = new HashMap<>();
        JSONObject locationObject = null;
        try {
            locationObject = LocationUtil.reverseGeoCode(longitudeFinal, latitudeFinal);
        } catch (Exception e) {
            log.info(e.getMessage());
            log.info("根据经纬度获取位置信息失败");
        }
        String locationStr = locationObject.getString("formattedAddress");
        returnDeviceProperties.put("deviceProperties", deviceProperties);
        returnDeviceProperties.put("manualId", manualId);
        returnDeviceProperties.put("location", locationStr);
        return AjaxResult.success(returnDeviceProperties);
    }


    /**
     * 设备初始化（新建设备）
     *
     * @param deviceMac
     * @return
     */
    @ApiOperation("deviceName")
    @PostMapping("/init")
    public AjaxResult getDeviceName(String deviceMac) {
        try {
            DeviceDao deviceDao = deviceService.getDeviceName(deviceMac);
            if (deviceDao != null) {
                return AjaxResult.success(deviceDao);
            } else {
                return AjaxResult.error("register device fail");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
            return AjaxResult.error("unknown error");
        }
    }

    /**
     * 分页拉取图片
     *
     * @param photoDao
     * @return
     */
    @ApiOperation("按日期，分页拉取图片，根据时间查找时，示例：" +
            "http://localhost:8184/device/photo/query?params%5BbeginTime%5D=2021-12-01&params%5BendTime%5D=2021-12-02")
    @GetMapping("/photo/query")
    public TableDataInfo getPhotoByDate(SelectPhotoDao photoDao) {
//        log.info(photoDao.getDeviceName());
        Long userIdL = SecurityUtils.getLoginUser().getUser().getUserId();
        int userId = userIdL.intValue();
        //管理员默认无单位，单位id就设为0
//        int userId = 1 ;
        Integer unitId = 0;
        if (userId != 1 && userId != 20) {
            unitId = unitUserMapper.selectByPrimaryKey(userId).getUnitId();
        }
        startPage();
        try {
            List<PhotoDao> photoDaos = photoService.selectPhotoList(photoDao, unitId);
            return getDataTable(photoDaos);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 重新自动计数
     *
     * @param id 记录编号
     * @return
     */
    @ApiOperation("重新自动计数")
    @GetMapping("/autoCountAgain")
    public AjaxResult autoCountAgain(int id) {
        Long userIdL = SecurityUtils.getLoginUser().getUser().getUserId();
        Integer userId = userIdL.intValue();
        Integer unitId = 0;
        if (userId != 1 && userId != 20) {
            unitId = unitUserMapper.selectByPrimaryKey(userId).getUnitId();
        }
        SelectPhotoDao detectionLogs = photoService.autoCountAgain(id, unitId);
        return AjaxResult.success(detectionLogs);
    }

    /**
     * 更新绘图信息以及虫子信息
     *
     * @return
     */
    @ApiOperation("更新绘图信息以及虫子信息" +
            "http://localhost:8184/device/drawByManual")
    @PostMapping("/drawByManual")
    public AjaxResult drawByManual(Integer id, String width, String height, String type, String position, Integer addOrCut) throws IOException {
        Long userIdL = SecurityUtils.getLoginUser().getUser().getUserId();
        Integer userId = userIdL.intValue();
        Integer unitId = 0;
        if (userId != 1 && userId != 20) {
            unitId = unitUserMapper.selectByPrimaryKey(userId).getUnitId();
        }
        SelectPhotoDao photoDao = modelService.drawByManual(unitId, id, width, height, type, position, addOrCut);
        return AjaxResult.success(photoDao);
    }

    /**
     * 获取所有虫子标签对应的画框颜色map
     *
     * @return
     */
    @GetMapping("/getColorTag")
    public HashMap<String, String> getColorTag() {
        HashMap<String, Color> tagColorHashMap = ImgDrawCircleTool.TagColorHashMap;
        HashMap<String, String> tagColorHexHashMap = new HashMap<>();
        for (Map.Entry<String, Color> entry : tagColorHashMap.entrySet()) {
            String tag = entry.getKey();
            Color color = entry.getValue();
            String hexColor = colorToHex(color);
            tagColorHexHashMap.put(tag, hexColor);
        }
//        根据tag排序
        List<Map.Entry<String, String>> sortedEntries = new ArrayList<>(tagColorHexHashMap.entrySet());
        Collections.sort(sortedEntries, Comparator.comparing(Map.Entry::getKey));
        HashMap<String, String> sortedTagColorHexHashMap = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : sortedEntries) {
            sortedTagColorHexHashMap.put(entry.getKey(), entry.getValue());
        }

        return sortedTagColorHexHashMap;
    }

    /**
     * 批量上传检测
     *
     * @param deviceName
     * @param files
     * @return
     * @throws IOException
     */
    @ApiOperation("批量上传检测")
    @PostMapping("/models")
    public AjaxResult models(String deviceName, @RequestParam("files") MultipartFile[] files) throws IOException {
        if (files.length != 0) {
            List<TraplightDetectionLog> result = new ArrayList<>();
            for (MultipartFile file : files) {
                log.info("filename" + file.getOriginalFilename());
//                // upload() : 返回的就是文件路径
//                String images = FileUploadUtils.upload(RuoYiConfig.getDetectionPath(), file);
//                String detectionImages = StringUtils.substringAfter(images, "profile");
//                PhotoDao photoDao = new PhotoDao();
//                String filename = file.getOriginalFilename();
//                photoDao.setPhotoName(filename).setDeviceName(deviceName);
//                if (dataMapper.selectPhotoByName(filename) == null){
//                    dataMapper.insertPhotoInfo(photoDao);
//                }
//                photoDao.setPhotoUpdateTime(SDF.format(new Date()));
//                photoDao.setThumbPath(images.replace("original", "thum"));
////                        .setPhotoTime(ParseString.string2Date(Objects.requireNonNull(file.getOriginalFilename())));
//                /* 解析识别结果构造实例存入数据库并返回, 检测不需要list集合，识别有多个可能，需要集合装载，其他的不需要 */
//                dataMapper.updatePhotoInfo(photoDao);
                // upload() : 返回的就是文件路径
                DeviceDao deviceDao = deviceMapper.selectDeviceByName(deviceName);
                String manualId = deviceDao.getManualId();
                String filename = file.getOriginalFilename(); //原始图片的名字
                SelectPhotoDao photoDao = dataMapper.selectPhotoByName(filename); //查询是否存在该图片
                if (photoDao != null) {
                    // 文件已存在，覆盖
                    FileUtils.deleteFile(photoDao.getPhotoPath().replace("/profile", profile));
                    FileUtils.deleteFile(photoDao.getThumbPath().replace("/profile", profile));
                    if (Objects.equals(photoDao.getIsModel(), "true")) {
                        photoDao.setIsModel("false");
                        dataMapper.updatePhotoInfo(photoDao);
                        if (photoDao.getResultPath() != null) {
                            FileUtils.deleteFile(photoDao.getResultPath().replace("/profile", profile));
                        }
                    }
                    log.info("文件已存在，进行覆盖");
                } else {
                    SelectPhotoDao newAddPhotoDao = new SelectPhotoDao().setPhotoName(filename).setDeviceName(deviceName)
                            .setPhotoUpdateTime(SDF.format(new Date())).setDeviceId(deviceDao.getDeviceId());
                    dataMapper.insertPhotoInfo(newAddPhotoDao);
                    log.info("新文件");
                }
                // InSeCt_1658646537312_0.jpg 时间戳+手动1/自动0
                String[] splitFileName = StringUtils.split(filename, '_');
                assert splitFileName != null;
                //在图片上添加设备信息
                String photoType = Integer.parseInt(splitFileName[2].replace(".jpg", "")) == 0 ? "自动" : "手动";
                BufferedImage image = ImageIO.read(file.getInputStream());
                // 在图片上添加时间信息
                BufferedImage imageWithTimestamp = ImageUtil.addTimestamp((SDF.format(Long.parseLong(StringUtils.split(filename, '_')[1]))), image);

                BufferedImage imageWithTimeAndDeviceId = ImageUtil.addDeviceId(manualId, imageWithTimestamp);
                //在图片上添加手动拍照或自动拍照的信息
                BufferedImage imageWithPhotoType = ImageUtil.addPhotoType(photoType, imageWithTimeAndDeviceId);
                // 将BufferedImage转换为自定义的MultipartFile
                MultipartFile multipartFileWithTimestamp = new BufferedImageMultipartFile(
                        imageWithPhotoType,
                        file.getName(),
                        file.getOriginalFilename()
                );
                String images = FileUploadUtils.upload(RuoYiConfig.getUploadPath() + String.format("/%s", deviceName), multipartFileWithTimestamp);
                String detectionImages = StringUtils.substringAfter(images, "profile");

                SelectPhotoDao newPhotoDao = new SelectPhotoDao().setPhotoName(filename).setDeviceName(deviceName);
                newPhotoDao.setPhotoPath(images).setThumbPath(images.replace("original", "thum"));
                newPhotoDao.setPhotoTime(SDF.format(Long.parseLong(splitFileName[1]))).setIsModel("true");
                newPhotoDao.setPhotoType(Integer.parseInt(splitFileName[2].replace(".jpg", "")));
                log.info("test:" + newPhotoDao);
//                dataMapper.updatePhotoInfo(newPhotoDao);
                List<TraplightDetectionLog> detectionLogList = new ArrayList<>();

                ImgDrawCircleTool tool = new ImgDrawCircleTool();
                // 图片发送到Django进行识别
//                try {
//                    ResponseEntity<String> responseEntity = Threads.detectionRequest(profile + detectionImages, detectionUrl);
//                    log.info("responseEntity------->" + responseEntity.getBody());
//                    // json格式的数据转换成数组格式
//                    detectionLogList = JSON.parseArray(responseEntity.getBody(), TraplightDetectionLog.class);
//                    //assert detectionLogList != null;
//                    log.info("detection:" + detectionLogList.toString());
//                } catch (Exception e){
//                    System.out.println(e.getMessage());
//                }
                // 图片调用远程rpc接口
                RpcRequest rpc = new RpcRequest("47.96.166.231", 10052, "siqing-files");
                try {
                    String upload_oss_name = StringUtils.substringAfter(images, "profile/");
//                    String res = rpc.getRpcRes(upload_oss_name);
                    String res = Threads.rpcRequest(upload_oss_name, rpc::getRpcRes);
                    log.info("responseEntity=======>" + res);
                    detectionLogList = JSON.parseArray(res, TraplightDetectionLog.class);
                    log.info(detectionLogList.toString());
                } catch (Exception e) {
                    System.out.println(e.getMessage());
                } finally {
                    rpc.shutdownChannel();
                }

                if (!detectionLogList.isEmpty()) {
                    for (TraplightDetectionLog detection : detectionLogList) {
                        log.info(detection.toString());
                        if (StringUtils.isNotEmpty(detection.getCorner())) {
                            detection.setImagePath(images).setOriginalFileName(filename);
                            /*画框之后的结果图 resUrl  缩略图 已添加 */
                            log.info("detectiontag:" + detection.getTag());
                            newPhotoDao.setTagForDraw(detection.getTag());
                            List<String> tagList = JSON.parseArray(detection.getTag(), String.class);
//                            log.info(tagList.toString());
                            //log.info("112222222 =" + SDF.format(Long.parseLong(splitFileName[1])));
                            //根据设备获取到该设备的所属单位id
                            SerDevicePermi devicePermiInfo = permiMapper.selectByDeviceSerial(deviceName);
                            Integer deviceId = devicePermiInfo.getId();
                            Integer unitId = deviceNameToUnit(deviceId);
                            if (unitId != 0) {
                                //获取虫情权限
                                List<DevicePermiInsectInfo> insectPermiLst = permiMapper.selectInsectListByDeviceId(deviceId);
                                //用于存储权限虫子的编号
                                List<String> retLst = new ArrayList<>();
                                for (DevicePermiInsectInfo insectPermi : insectPermiLst) {
                                    String ret = insectPermi.getRet();
                                    if (!retLst.contains(ret)) {
                                        retLst.add(ret);
                                    }
                                }
                                //原始框信息
                                List<int[]> cornerList = detection.getCorner();
                                log.info("原始框信息1：" + JSON.toJSONString(detection.getCorner()));


                                //用户独属的框信息
                                List<int[]> cornerListForUser = new ArrayList<>(cornerList);
                                //用户独属的虫子信息
                                List<String> tagListForUser = new ArrayList<>(tagList);
                                //在遍历tagList的过程中，记录需要删除的索引位置
                                List<Integer> indexesToRemove = new ArrayList<>();
                                for (int i = 0; i < tagListForUser.size(); i++) {
                                    String tagValue = tagListForUser.get(i);
                                    if (!retLst.contains(tagValue)) {
                                        indexesToRemove.add(i);
                                    }
                                }
                                //删除不需要的虫子信息
                                for (int i = indexesToRemove.size() - 1; i >= 0; i--) {
                                    int indexToRemove = indexesToRemove.get(i);
                                    tagListForUser.remove(indexToRemove);
                                    cornerListForUser.remove(indexToRemove);
                                }
                                log.info("tagForUser: " + tagListForUser.toString() + "\ncornerForUser:" + JSON.toJSONString(cornerListForUser));
                                if (!tagListForUser.isEmpty() && !cornerListForUser.isEmpty()) {
                                    newPhotoDao.setTagForUser(ParseString.getTagNum(JSON.toJSONString(tagListForUser))).setCornerForUser(JSON.toJSONString(cornerListForUser));
                                    //绘制用户专属的结果图片
//                                    String resultPathForUser = tool.doDrawRectangleForUnit(unitId, cornerListForUser, tagListForUser, profile + detectionImages).replace(profile, Constants.RESOURCE_PREFIX);
//                                    log.info("用户的结果图的url：" + resultPathForUser);
                                }
                            }
//                            log.info("原始框信息2：" + JSON.toJSONString(detection.getCorner()));
                            String resultPath = tool.doDrawRectangleT(detection.getCorner(), tagList, profile + detectionImages).replace(profile, Constants.RESOURCE_PREFIX);
                            detection.setTag(ParseString.getTagNum(detection.getTag()));
                            detection.setStrCorner(JSON.toJSONString(detection.getCorner()));
                            newPhotoDao.setTag(detection.getTag()).setTagManual(detection.getTag()).setCorner(detection.getStrCorner())
                                    .setPhotoName(detection.getOriginalFileName())
                                    .setResultPath(resultPath);
                            modelService.insertDetectionLog(detection);
                            log.info("成功识别到目标，结果已入库");
                        } else {
                            newPhotoDao.setPhotoName(filename).setResultPath(images);
                            log.info("未识别到目标，开始识别下一张图片");
                        }
                        dataMapper.updatePhotoInfo(newPhotoDao);
                        log.info(newPhotoDao.toString());
                    }
                } else {
                    dataMapper.updatePhotoInfo(newPhotoDao);
                    log.info("lastInfo" + newPhotoDao);
                }
                result.addAll(detectionLogList);
            }
            return AjaxResult.success(result);
        }
        return AjaxResult.error("上传图片异常");
    }

    /**
     * 调用模型检测
     *
     * @param deviceName
     * @param file
     * @return
     * @throws IOException
     */
    @ApiOperation("调用模型检测")
    @PostMapping("/model")
    public AjaxResult model(String deviceName, @RequestParam("imageName") MultipartFile file) throws IOException {
        if (!file.isEmpty()) {
            log.info("filename" + file.getOriginalFilename());
//                // upload() : 返回的就是文件路径
//                String images = FileUploadUtils.upload(RuoYiConfig.getDetectionPath(), file);
//                String detectionImages = StringUtils.substringAfter(images, "profile");
//                PhotoDao photoDao = new PhotoDao();
//                String filename = file.getOriginalFilename();
//                photoDao.setPhotoName(filename).setDeviceName(deviceName);
//                if (dataMapper.selectPhotoByName(filename) == null){
//                    dataMapper.insertPhotoInfo(photoDao);
//                }
//                photoDao.setPhotoUpdateTime(SDF.format(new Date()));
//                photoDao.setThumbPath(images.replace("original", "thum"));
////                        .setPhotoTime(ParseString.string2Date(Objects.requireNonNull(file.getOriginalFilename())));
//                /* 解析识别结果构造实例存入数据库并返回, 检测不需要list集合，识别有多个可能，需要集合装载，其他的不需要 */
//                dataMapper.updatePhotoInfo(photoDao);
            // upload() : 返回的就是文件路径
            DeviceDao deviceDao = deviceMapper.selectDeviceByName(deviceName);
            String manualId = deviceDao.getManualId();
            String filename = file.getOriginalFilename(); //原始图片的名字
            SelectPhotoDao photoDao = dataMapper.selectPhotoByName(filename); //查询是否存在该图片
            if (photoDao != null) {
                // 文件已存在，覆盖
                FileUtils.deleteFile(photoDao.getPhotoPath().replace("/profile", profile));
                FileUtils.deleteFile(photoDao.getThumbPath().replace("/profile", profile));
                if (Objects.equals(photoDao.getIsModel(), "true")) {
                    photoDao.setIsModel("false");
                    dataMapper.updatePhotoInfo(photoDao);
                    if (photoDao.getResultPath() != null) {
                        FileUtils.deleteFile(photoDao.getResultPath().replace("/profile", profile));
                    }
                }
                log.info("文件已存在，进行覆盖");
            } else {
                SelectPhotoDao newAddPhotoDao = new SelectPhotoDao().setPhotoName(filename).setDeviceName(deviceName)
                        .setPhotoUpdateTime(SDF.format(new Date())).setDeviceId(deviceDao.getDeviceId());
                dataMapper.insertPhotoInfo(newAddPhotoDao);
                log.info("新文件");
            }
            // InSeCt_1658646537312_0.jpg 时间戳+手动1/自动0
            String[] splitFileName = StringUtils.split(filename, '_');
            assert splitFileName != null;
            String photoType = Integer.parseInt(splitFileName[2].replace(".jpg", "")) == 0 ? "自动" : "手动";
            BufferedImage image = ImageIO.read(file.getInputStream());
            // 在图片上添加时间信息
            BufferedImage imageWithTimestamp = ImageUtil.addTimestamp((SDF.format(Long.parseLong(StringUtils.split(filename, '_')[1]))), image);
            //在图片上添加设备信息
            BufferedImage imageWithTimeAndDeviceId = ImageUtil.addDeviceId(manualId, imageWithTimestamp);
            //在图片上添加手动拍照或自动拍照的信息
            BufferedImage imageWithPhotoType = ImageUtil.addPhotoType(photoType, imageWithTimeAndDeviceId);
            // 将BufferedImage转换为自定义的MultipartFile
            MultipartFile multipartFileWithTimestamp = new BufferedImageMultipartFile(
                    imageWithPhotoType,
                    file.getName(),
                    file.getOriginalFilename()
            );
            String images = FileUploadUtils.upload(RuoYiConfig.getUploadPath() + String.format("/%s", deviceName), multipartFileWithTimestamp);
            String detectionImages = StringUtils.substringAfter(images, "profile");
            SelectPhotoDao newPhotoDao = new SelectPhotoDao().setPhotoName(filename).setDeviceName(deviceName);
            newPhotoDao.setPhotoPath(images).setThumbPath(images.replace("original", "thum"));

            newPhotoDao.setPhotoTime(SDF.format(Long.parseLong(splitFileName[1]))).setIsModel("true");
            newPhotoDao.setPhotoType(Integer.parseInt(splitFileName[2].replace(".jpg", "")));
            log.info("test:" + newPhotoDao);
//                dataMapper.updatePhotoInfo(newPhotoDao);
            List<TraplightDetectionLog> detectionLogList = new ArrayList<>();
            ImgDrawCircleTool tool = new ImgDrawCircleTool();
            // 图片发送到Django进行识别
//                try {
//                    ResponseEntity<String> responseEntity = Threads.detectionRequest(profile + detectionImages, detectionUrl);
//                    log.info("responseEntity------->" + responseEntity.getBody());
//                    // json格式的数据转换成数组格式
//                    detectionLogList = JSON.parseArray(responseEntity.getBody(), TraplightDetectionLog.class);
//                    //assert detectionLogList != null;
//                    log.info("detection:" + detectionLogList.toString());
//                } catch (Exception e){
//                    System.out.println(e.getMessage());
//                }
            // 图片调用远程rpc接口
            RpcRequest rpc = new RpcRequest("47.96.166.231", 10052, "siqing-files");
            try {
                String upload_oss_name = StringUtils.substringAfter(images, "profile/");
//                    String res = rpc.getRpcRes(upload_oss_name);
                String res = Threads.rpcRequest(upload_oss_name, rpc::getRpcRes);
                log.info("responseEntity=======>" + res);
                detectionLogList = JSON.parseArray(res, TraplightDetectionLog.class);
                log.info(detectionLogList.toString());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            } finally {
                rpc.shutdownChannel();
            }

            if (!detectionLogList.isEmpty()) {
                for (TraplightDetectionLog detection : detectionLogList) {
                    log.info(detection.toString());
                    if (StringUtils.isNotEmpty(detection.getCorner())) {
                        detection.setImagePath(images).setOriginalFileName(filename);
                        /*画框之后的结果图 resUrl  缩略图 已添加 */
                        log.info("detectiontag:" + detection.getTag());
                        newPhotoDao.setTagForDraw(detection.getTag());
                        List<String> tagList = JSON.parseArray(detection.getTag(), String.class);
                        log.info(tagList.toString());
                        //根据设备获取到该设备的所属单位id
                        SerDevicePermi devicePermiInfo = permiMapper.selectByDeviceSerial(deviceName);
                        Integer deviceId = devicePermiInfo.getId();
                        Integer unitId = deviceNameToUnit(deviceId);
                        if (unitId != 0) {
                            //获取虫情权限
                            List<DevicePermiInsectInfo> insectPermiLst = permiMapper.selectInsectListByDeviceId(deviceId);
                            //用于存储权限虫子的编号
                            List<String> retLst = new ArrayList<>();
                            for (DevicePermiInsectInfo insectPermi : insectPermiLst) {
                                String ret = insectPermi.getRet();
                                if (!retLst.contains(ret)) {
                                    retLst.add(ret);
                                }
                            }
                            //原始框信息
                            List<int[]> cornerList = detection.getCorner();
                            log.info("原始框信息1：" + JSON.toJSONString(detection.getCorner()));


                            //用户独属的框信息
                            List<int[]> cornerListForUser = new ArrayList<>(cornerList);
                            //用户独属的虫子信息
                            List<String> tagListForUser = new ArrayList<>(tagList);
                            //在遍历tagList的过程中，记录需要删除的索引位置
                            List<Integer> indexesToRemove = new ArrayList<>();
                            for (int i = 0; i < tagListForUser.size(); i++) {
                                String tagValue = tagListForUser.get(i);
                                if (!retLst.contains(tagValue)) {
                                    indexesToRemove.add(i);
                                }
                            }
                            //删除不需要的虫子信息
                            for (int i = indexesToRemove.size() - 1; i >= 0; i--) {
                                int indexToRemove = indexesToRemove.get(i);
                                tagListForUser.remove(indexToRemove);
                                cornerListForUser.remove(indexToRemove);
                            }
                            log.info("tagForUser: " + tagListForUser.toString() + "\ncornerForUser:" + JSON.toJSONString(cornerListForUser));
                            if (!tagListForUser.isEmpty() && !cornerListForUser.isEmpty()) {
                                newPhotoDao.setTagForUser(ParseString.getTagNum(JSON.toJSONString(tagListForUser))).setCornerForUser(JSON.toJSONString(cornerListForUser));
                            }
                            //绘制用户专属的结果图片
                            if (!tagListForUser.isEmpty() && !cornerListForUser.isEmpty()) {
//                                    String resultPathForUser = tool.doDrawRectangleForUnit(unitId, cornerListForUser, tagListForUser, profile + detectionImages).replace(profile, Constants.RESOURCE_PREFIX);
//                                    log.info("用户的结果图的url：" + resultPathForUser);
                            }
                        }
                        log.info("原始框信息2：" + JSON.toJSONString(detection.getCorner()));
                        String resultPath = tool.doDrawRectangleT(detection.getCorner(), tagList, profile + detectionImages).replace(profile, Constants.RESOURCE_PREFIX);
                        detection.setTag(ParseString.getTagNum(detection.getTag()));
                        detection.setStrCorner(JSON.toJSONString(detection.getCorner()));
                        newPhotoDao.setTag(detection.getTag()).setTagManual(detection.getTag()).setCorner(detection.getStrCorner())
                                .setPhotoName(detection.getOriginalFileName())
                                .setResultPath(resultPath);
                        modelService.insertDetectionLog(detection);
                        log.info("成功识别到目标，结果已入库");
                    } else {
                        newPhotoDao.setPhotoName(filename).setResultPath(images);
                        log.info("未识别到目标，开始识别下一张图片");
                    }
                    dataMapper.updatePhotoInfo(newPhotoDao);
                    log.info(newPhotoDao.toString());
                }
            } else {
                dataMapper.updatePhotoInfo(newPhotoDao);
                log.info("lastInfo" + newPhotoDao);
            }
            return AjaxResult.success(detectionLogList);
        }
        return AjaxResult.error("上传图片异常");
    }

    /**
     * 根据测报灯id取得对应的unitId
     *
     * @param deviceId
     * @return
     */
    private Integer deviceNameToUnit(Integer deviceId) {
//        没有分配给地块的设备
        if (blockDeviceMapper.selectByPrimaryKey(deviceId) == null) {
            return 0;
        }
        Integer blockId = blockDeviceMapper.selectByPrimaryKey(deviceId).getBlockId();
        Integer baseId = baseBlockMapper.selectByPrimaryKey(blockId).getBaseId();
        Integer unitId = unitBaseMapper.selectByPrimaryKey(baseId).getUnitId();
        if (unitId != null) {
            return unitId;
        } else {
            //未分配的设备
            return 0;
        }
    }

    /**
     * Color转16进制
     *
     * @param color
     * @return
     */
    public static String colorToHex(Color color) {
        return String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue());
    }

    //    @ApiOperation("调用模型检测")
//    @PostMapping("/upload")
    public AjaxResult upload(String deviceName, @RequestParam("imageName") MultipartFile file) {
        try {
            if (!file.isEmpty()) {
                // upload() : 返回的就是文件路径
                String filename = file.getOriginalFilename();
                SelectPhotoDao photoDao = dataMapper.selectPhotoByName(filename);
                if (photoDao != null) {
                    // 文件已存在，覆盖
                    FileUtils.deleteFile(photoDao.getPhotoPath().replace("/profile", profile));
                    FileUtils.deleteFile(photoDao.getThumbPath().replace("/profile", profile));
                    if (Objects.equals(photoDao.getIsModel(), "true")) {
                        photoDao.setIsModel("false");
                        dataMapper.updatePhotoInfo(photoDao);
                        FileUtils.deleteFile(photoDao.getResultPath().replace("/profile", profile));
                    }
                    log.info("文件已存在，进行覆盖");
                } else {
                    SelectPhotoDao newPhotoDao = new SelectPhotoDao().setPhotoName(filename).setDeviceName(deviceName).setPhotoUpdateTime(SDF.format(new Date()));
                    dataMapper.insertPhotoInfo(newPhotoDao);
                    log.info("新文件");
                }
                String images = FileUploadUtils.upload(RuoYiConfig.getUploadPath(), file);
                SelectPhotoDao newPhotoDao = new SelectPhotoDao().setPhotoName(filename).setDeviceName(deviceName);
                newPhotoDao.setPhotoPath(images).setThumbPath(images.replace("original", "thum"));
                // InSeCt_1658646537312_0.jpg 时间戳+手动1/自动0
                String[] splitFileName = StringUtils.split(filename, '_');
                assert splitFileName != null;
                newPhotoDao.setPhotoTime(SDF.format(Long.parseLong(splitFileName[1]))).setIsModel("false");
                newPhotoDao.setPhotoType(Integer.parseInt(splitFileName[2].replace(".png", "")));
                dataMapper.updatePhotoInfo(newPhotoDao);
                detectionVoidRequest(images.replace("/profile", profile), detectionUrl);
                return AjaxResult.success("success");
            } else {
                return AjaxResult.error("wrong file");
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return AjaxResult.error("upload fail");
    }

    public static void detectionResult(String pathName, ResponseEntity<String> responseEntity) {
        // 图片发送到Django进行识别
        log.info("responseEntity------->" + responseEntity.getBody());
        SelectPhotoDao photoDao = staticDataMapper.selectPhotoByPath(pathName.replace(staticProfile, "/profile"));
        String filename = photoDao.getPhotoName();
        String[] splitFileName = StringUtils.split(filename, '_');
        photoDao.setIsModel("true");
        String images = photoDao.getPhotoPath().replace("/profile", staticProfile);
        String detectionImages = StringUtils.substringAfter(images, "profile");
        List<TraplightDetectionLog> detectionLogList = new ArrayList<>();
        ImgDrawCircleTool tool = new ImgDrawCircleTool();
        // json格式的数据转换成数组格式
        detectionLogList = JSON.parseArray(responseEntity.getBody(), TraplightDetectionLog.class);
        assert detectionLogList != null;
        log.info(detectionLogList.toString());
        for (TraplightDetectionLog detection : detectionLogList) {
            log.info(detection.toString());
            if (StringUtils.isNotEmpty(detection.getCorner())) {
                detection.setImagePath(images).setOriginalFileName(photoDao.getPhotoName());
                /*画框之后的结果图 resUrl  缩略图 已添加 */
                List<String> tagList = JSON.parseArray(detection.getTag(), String.class);
                String resultPath = tool.doDrawRectangleT(detection.getCorner(), tagList, staticProfile + detectionImages).replace(staticProfile, Constants.RESOURCE_PREFIX);
                detection.setTag(ParseString.getTagNum(detection.getTag()));
                detection.setStrCorner(JSON.toJSONString(detection.getCorner()));
                photoDao.setTag(detection.getTag()).setCorner(detection.getStrCorner()).setIsModel("true")
                        .setResultPath(resultPath);
                staticDataMapper.updatePhotoInfo(photoDao);
                staticmodelService.insertDetectionLog(detection);
                log.info("成功识别到目标，结果已入库");
            } else {
                log.info("未识别到目标，开始识别下一张图片");
            }
        }
//        return AjaxResult.success(detectionLogList);
    }
}
